package service;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;

import org.apache.log4j.Logger;

import crawler.CrawlerDocument;
import crawler.DocumentPool;

public class Dumper implements Runnable {
	
	private final Logger logger = Logger.getLogger(Dumper.class);
	
	private static Dumper self = null;
	
	private static String dumpFilePattern = 
		GlobalConfiguration.getInstance().get("dump_file_patt");
	private int dumpTimeout = 
		Integer.parseInt(GlobalConfiguration.getInstance().get("dump_timeout"));
	private int dumpThreshold = 
		Integer.parseInt(GlobalConfiguration.getInstance().get("dump_thres"));
	
	private DocumentPool _pool = null;

	
	private Dumper(){

		this._pool = new DocumentPool();
	}
	
	public static Dumper getInstance(){
		if (null == self){
			self = new Dumper();
		}

		return self;
	}
	
	public void put(CrawlerDocument doc){
		try {
			_pool.put(doc);
		} catch (InterruptedException e) {
			logger.error("{}",e );
		}
	}

	@Override
	public void run() {
		
		String filename = dumpFilePattern; 
		File dumpFile = new File(filename);
		BufferedWriter fout = null;
		
		try {
			fout = new BufferedWriter(new FileWriter(dumpFile, true));
		} catch (IOException e) {
			logger.error("{}", e);
		}
		
		int currDumpCnt = 0;
		long currDumpStart = getNowMiliSeconds();
		
		while(true){
			
			while(_pool.size() > 0){
				
				logger.debug("pool size: " + _pool.size() + ", currDumpCnt = " + currDumpCnt);
				
				// Dump a document
				try {
					CrawlerDocument doc = this._pool.take();
					this.dump(fout, doc);	
				} catch (InterruptedException e) {
					logger.error("{}", e);
				}
				currDumpCnt++;
				
				// Change dump file name and create a new current file to dump
				// TODO : Use file id, not time stamp
							
				long nowMiliSeconds = getNowMiliSeconds();
				long dumpTimpGap = nowMiliSeconds - currDumpStart;
				if (currDumpCnt > dumpThreshold || dumpTimpGap > dumpTimeout * 1000){
					
					logger.debug("currDumpCnt = " + currDumpCnt +", dumpTimeGap = " + dumpTimpGap);
										
					long nowSeconds = nowMiliSeconds / 1000;
					String savename = dumpFilePattern + "." + nowSeconds;
					logger.debug("New dump file name = " + savename + ", pool size : " + _pool.size());
					try {						
						fout.close();
						dumpFile.renameTo(new File(savename));
						fout = new BufferedWriter(new FileWriter(dumpFile, true));
					} catch (IOException e) {
						logger.error("{}", e);
					}
					
					currDumpCnt = 0;
					currDumpStart = getNowMiliSeconds();;				
				}	
				//try {
				//	Thread.sleep(1);
				//} catch (InterruptedException e) {
				//	logger.error("{}", e);
				//}
							
			}
			
			// Sleep if no data in 
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				logger.error("{}", e);
			}			
			
		}

	}
	
	private void dump(BufferedWriter fout, CrawlerDocument doc){
		
		if (null == doc){
			logger.warn("doc is null");
			return;
		}
		
		logger.debug("Dumping doc : " + doc.getFeature("link"));
		
		try {
			fout.write("link = "+ doc.getFeature("link") + "\n");
			fout.write("image = " + doc.getFeature("image") + "\n");
			fout.write("text = " + doc.getFeature("title") + "\n");
			fout.write("ori_price = " + doc.getFeature("ori_price") + "\n");
			fout.write("cur_price = " + doc.getFeature("cur_price") + "\n");
			fout.write("----------------------------------------" + "\n");			
		} catch (IOException e) {
			logger.error("{}", e);
		}

	}
	
	private long getNowMiliSeconds(){
		Date now = new Date();
		long time = now.getTime();
		return time;
	}

}
